<template>
  <div>
    <div class="Calendar">
      <div class="header">
        <div class="header_left">
          <div class="prev_btn" @click="prevSwiper">
            <i class="iconfont icon-jiantou"></i>
          </div>
          {{ showTitle }}
          <div class="next_btn" @click="nextSwiper">
            <i class="iconfont icon-jiantou r180"></i>
          </div>
        </div>
        <div class="header_right">
          <div
            class="header_right_btn"
            @click="changeType('month')"
            :class="data.type === 'month' && 'active'"
          >
            <i class="iconfont icon-yueshitu"></i>
            <span>月</span>
          </div>
          <div
            class="header_right_btn"
            @click="changeType('week')"
            :class="data.type === 'week' && 'active'"
          >
            <i class="iconfont icon-zhoushitu"></i>
            <span>周</span>
          </div>
        </div>
      </div>
      <div class="main">
        <div class="title">
          <div class="title_item"><div class="text">日</div></div>
          <div class="title_item"><div class="text">一</div></div>
          <div class="title_item"><div class="text">二</div></div>
          <div class="title_item"><div class="text">三</div></div>
          <div class="title_item"><div class="text">四</div></div>
          <div class="title_item"><div class="text">五</div></div>
          <div class="title_item"><div class="text">六</div></div>
        </div>
        <div
          :class="data.listHeight === 5 ? 'list_height5' : 'list_height6'"
          v-if="data.type === 'month'"
        >
          <van-swipe
            @change="monthChange"
            initial-swipe="1"
            :loop="true"
            :show-indicators="false"
            ref="monthRef"
          >
            <van-swipe-item v-for="(cur, index) in data.monthArr" :key="index"
              ><div class="list">
                <div
                  class="list_item"
                  @click="handelClick(item)"
                  v-for="(item, index) in cur"
                  :key="index"
                >
                  <div
                    v-if="!item.today"
                    class="num"
                    :class="{
                      num_noy_month: item.month !== curMonth,
                      active: item.formatDate === nowDateStr,
                    }"
                  >
                    {{ item.day }}
                  </div>
                  <div
                    v-else
                    class="num num_today"
                    :class="{
                      active: item.formatDate === nowDateStr,
                    }"
                  >
                    今
                  </div>
                  <div
                    v-if="item.data && item.data.color"
                    class="dot"
                    :class="`${item.data.color}`"
                  ></div>
                </div></div
            ></van-swipe-item>
          </van-swipe>
        </div>
        <div v-if="data.type === 'week'">
          <van-swipe
            @change="weekChange"
            initial-swipe="1"
            :loop="true"
            :show-indicators="false"
            ref="weekRef"
          >
            <van-swipe-item v-for="(cur, index) in data.weekArr" :key="index"
              ><div class="list">
                <div
                  class="list_item"
                  @click="handelClick(item)"
                  v-for="(item, index) in cur"
                  :key="index"
                >
                  <div
                    v-if="!item.today"
                    class="num"
                    :class="{
                      num_noy_month: item.month !== curMonth,
                      active: item.formatDate === nowDateStr,
                    }"
                  >
                    {{ item.day }}
                  </div>
                  <div
                    v-else
                    class="num num_today"
                    :class="{
                      active: item.formatDate === nowDateStr,
                    }"
                  >
                    今
                  </div>
                  <div
                    v-if="item.data && item.data.color"
                    class="dot"
                    :class="`${item.data.color}`"
                  ></div>
                </div></div
            ></van-swipe-item>
          </van-swipe>
        </div>
      </div>
    </div>

    <div>当前时间：{{ data.nowObj.formatDate }}</div>
  </div>
</template>

<script setup>
import {
  getMonthDays,
  getPrevMonthWeekDay,
  getNextMonthWeekDay,
  createDateStr,
  formatDate,
} from "./date";
import { dataListArr } from "./data";
import { computed, reactive, ref } from "vue";
import { Swipe as VanSwipe, SwipeItem as VanSwipeItem } from "vant";
const data = reactive({
  nowDate: new Date(), //当前月的信息或者时当前周的信息 默认为今天
  activeDate: new Date(), //点击的那个日期 默认为今天
  monthList: [], //废弃，暂时没没用
  type: "month", //视图切换
  weekArr: [[], [], []], //周视图swiper的渲染数组
  monthArr: [[], [], []], //月视图swiper的渲染数组
  weekIndex: 1, //周视图swiper的当前项
  monthIndex: 1, //月视图swiper的当前项
  listHeight: 5, //视图高度
  nowObj: {},
});
// 定义计算属性 showTitle 展示年月
const showTitle = computed(() => {
  let month = data.nowDate.getMonth() + 1;
  month = month < 10 ? `0${month}` : month;
  return `${data.nowDate.getFullYear()}年${month}月`;
});
// 定义计算属性 curYear 动态更新年份
const curYear = computed(() => {
  return data.nowDate.getFullYear();
});
// 定义计算属性 curMonth 动态更新月份
const curMonth = computed(() => {
  return data.nowDate.getMonth();
});
// 定义计算属性 curDay 动态更新当前日
const curDay = computed(() => {
  return data.nowDate.getDate();
});
// 定义计算属性 prevWeek 动态更新上一周的信息 也就是当前日-7 获取上一周
const prevWeek = computed(() => {
  return new Date(
    data.nowDate.getFullYear(),
    data.nowDate.getMonth(),
    data.nowDate.getDate() - 7
  );
});
// 定义计算属性 nextWeek 动态更新下一周的信息 也就是当前日+7 获取下一周
const nextWeek = computed(() => {
  return new Date(
    data.nowDate.getFullYear(),
    data.nowDate.getMonth(),
    data.nowDate.getDate() + 7
  );
});
// 定义计算属性 prevMonth 动态更新上个月的信息 也就是当前月-1 获取上个月
const prevMonth = computed(() => {
  return new Date(data.nowDate.getFullYear(), data.nowDate.getMonth() - 1, 1);
});
// 定义计算属性 nextMonth 动态更新下个月的信息 也就是当前月-1 获取下个月
const nextMonth = computed(() => {
  return new Date(data.nowDate.getFullYear(), data.nowDate.getMonth() + 1, 1);
});
// 定义计算属性 monthDay 获取当前月有多少天 这个暂时没用到
const monthDay = computed(() => {
  return getMonthDays(new Date(curYear.value, curMonth.value, curDay.value));
});
// 定义计算属性 nowDateStr 动态获取当前日期字符串 2022-06-04 这样子的
const nowDateStr = computed(() => {
  return formatDate(data.activeDate);
});
// 定义swiper的ref
const monthRef = ref();
const weekRef = ref();

// ? 方法
// 通过定义swiper的ref 给按钮绑定事件 参考vant的swiper
const prevSwiper = () => {
  if (data.type === "month") {
    monthRef.value?.prev();
  } else {
    weekRef.value?.prev();
  }
};
const nextSwiper = () => {
  if (data.type === "month") {
    monthRef.value?.next();
  } else {
    weekRef.value?.next();
  }
};
/**
 * 传入月份信息  获取该月份的渲染数组
 */
const createMonthList = (date) => {
  const year = date.getFullYear();
  const month = date.getMonth();
  const monthDay = getMonthDays(
    new Date(date.getFullYear(), date.getMonth(), date.getDate())
  );
  // const day = date.getDate()
  // 这里是填补前面空缺的
  const prevArr = getPrevMonthWeekDay(date);
  let curArr = [];
  // 这是当月的
  for (let i = 1; i <= monthDay; i++) {
    let dayObj = {
      year: year,
      month: month,
      day: i,
      formatDate: createDateStr(year, month, i),
    };
    curArr.push(dayObj);
  }
  // 这是下个月的
  const nextMonth = getNextMonthWeekDay(date);
  return [...prevArr, ...curArr, ...nextMonth];
};
/**
 * 当月份改变的时候 整合信息obj
 * startTime：2022-05-29
 * endTime：2022-07-02
 */
const emitChangeMonth = () => {
  let len = data.monthArr[data.monthIndex].length - 1;
  let obj = {
    startTime: data.monthArr[data.monthIndex][0].formatDate,
    endTime: data.monthArr[data.monthIndex][len].formatDate,
  };
};
/**
 * 创建月份的对应的swiper数组
 * 我设定了swiper的初始状态是1 monthArr初始状态中monthArr[1]是当前月
 */
const createMonthData = (index) => {
  data.monthArr[0] = createMonthList(prevMonth.value);
  data.monthArr[1] = createMonthList(data.nowDate);
  data.monthArr[2] = createMonthList(nextMonth.value);
  emitChangeMonth();
};
/**
 * 当月份的swiper变化时 更换渲染数组达到切换效果
 * 当swiper的index为1时 monthArr[0]=上个月 monthArr[1]为当前月 monthArr[2]为下个月
 * 当swiper的index为0时 monthArr[0]=当前月 monthArr[1]为下个月 monthArr[2]为上个月
 * 当swiper的index为2时 monthArr[0]=下个月 monthArr[1]为上个月 monthArr[2]为当前月
 *
 * 这样动态的更新数组 可以保证，swiper的切换时正确的 swiper我只设定了3个了 留意一下
 */
const monthChange = (index) => {
  const curDate = data.monthArr[index][15];
  data.nowDate = new Date(curDate.year, curDate.month, 1);
  // console.log(curDate)
  if (index === 0) {
    data.monthArr[0] = createMonthList(data.nowDate);
    data.monthArr[1] = createMonthList(nextMonth.value);
    data.monthArr[2] = createMonthList(prevMonth.value);
  } else if (index === 1) {
    data.monthArr[0] = createMonthList(prevMonth.value);
    data.monthArr[1] = createMonthList(data.nowDate);
    data.monthArr[2] = createMonthList(nextMonth.value);
  } else if (index === 2) {
    data.monthArr[0] = createMonthList(nextMonth.value);
    data.monthArr[1] = createMonthList(prevMonth.value);
    data.monthArr[2] = createMonthList(data.nowDate);
  }
  data.monthIndex = index;
  //**这个是动态 修改容易的高度 让高度合理的显示
  data.listHeight = data.monthArr[index].length === 42 ? 6 : 5;
};
//创建周列表
const createWeekList = (date) => {
  const year = date.getFullYear();
  const month = date.getMonth();
  const day = date.getDate();
  const weekDay = date.getDay();
  let prevArr = [];
  for (let i = 1; i <= weekDay; i++) {
    let prevDate = new Date(year, month, day - i);
    let dayObj = {
      year: prevDate.getFullYear(),
      month: prevDate.getMonth(),
      day: prevDate.getDate(),
      formatDate: createDateStr(
        prevDate.getFullYear(),
        prevDate.getMonth(),
        prevDate.getDate()
      ),
    };
    prevArr.unshift(dayObj);
  }
  let nextArr = [];
  for (let j = 0; j <= 6 - weekDay; j++) {
    let nextDate = new Date(year, month, day + j);
    let dayObj = {
      year: nextDate.getFullYear(),
      month: nextDate.getMonth(),
      day: nextDate.getDate(),
      formatDate: createDateStr(
        nextDate.getFullYear(),
        nextDate.getMonth(),
        nextDate.getDate()
      ),
    };
    nextArr.push(dayObj);
  }
  return [...prevArr, ...nextArr];
};
/**
 * 创建周的对应的swiper数组
 * 我设定了swiper的初始状态是1 weekArr初始状态中weekArr[1]是当前月
 */
const createWeekData = () => {
  data.weekArr[0] = createWeekList(prevWeek.value);
  data.weekArr[1] = createWeekList(data.nowDate);
  data.weekArr[2] = createWeekList(nextWeek.value);
};
/**
 * 同月份的道理
 */
const weekChange = (index) => {
  const curDate = data.weekArr[index][1];
  data.nowDate = new Date(curDate.year, curDate.month, curDate.day);
  if (index === 0) {
    data.weekArr[0] = createWeekList(data.nowDate);
    data.weekArr[1] = createWeekList(nextWeek.value);
    data.weekArr[2] = createWeekList(prevWeek.value);
  } else if (index === 1) {
    data.weekArr[0] = createWeekList(prevWeek.value);
    data.weekArr[1] = createWeekList(data.nowDate);
    data.weekArr[2] = createWeekList(nextWeek.value);
  } else if (index === 2) {
    data.weekArr[0] = createWeekList(nextWeek.value);
    data.weekArr[1] = createWeekList(prevWeek.value);
    data.weekArr[2] = createWeekList(data.nowDate);
  }
  data.weekIndex = index;
};
/**
 * 点击对应的日期 将信息整合
 */
const handelClick = (item) => {
  // data.nowDate = new Date(item.year, item.month, item.day);
  data.activeDate = new Date(item.year, item.month, item.day);
  let details = [];
  let totalTime = 0;
  if (item.data) {
    details = item.data.details;
    totalTime = item.data.totalTime;
  }
  data.nowObj = item;
};
/**
 * 当有后端数据时 这么操作
 */
const changeShowList = (list) => {
  if (data.type === "month") {
    const _arr = data.monthArr[data.monthIndex].reduce((acc, item) => {
      item.data = list.filter((cur) => {
        if (cur.printDate === item.formatDate) {
          return cur;
        }
      })[0];
      if (item.formatDate === formatDate(new Date())) {
        item.today = true;
        if (item.data) {
          // data.$emit('update:totalTime', item.data.totalTime)
          // data.$emit('update:details', item.data.details)
        }
      }
      acc.push(item);
      return acc;
    }, []);
    data.monthArr.splice(data.monthIndex, 1, _arr);
  }

  // 星期的
  if (data.type === "week") {
    const _arr1 = data.weekArr[data.weekIndex].reduce((acc, item) => {
      item.data = list.filter((cur) => {
        if (cur.printDate === item.formatDate) {
          return cur;
        }
      })[0];
      if (item.formatDate === formatDate(new Date())) {
        item.today = true;
        console.log(444);
        if (item.data) {
          // data.$emit('update:totalTime', item.data.totalTime)
          // data.$emit('update:details', item.data.details)
        }
      }
      acc.push(item);
      return acc;
    }, []);
    data.weekArr.splice(data.weekIndex, 1, _arr1);
  }
};
/**
 * 点击切换视图
 */
const changeType = (type) => {
  data.type = type;
  if (data.type === "week") {
    data.weekIndex = 1;
    createWeekData();
  } else {
    data.monthIndex = 1;
    createMonthData();
    data.listHeight = data.monthArr[1].length === 42 ? 6 : 5;
  }
  // changeShowList(data.list);
};
/**
 * 初始化状态
 */
const init = () => {
  createMonthData();
  createWeekData();
  // 模拟接口请求
  setTimeout(() => {
    changeShowList(dataListArr);
  }, 2000);
};
init();
</script>

<style lang="less" scoped>
.Calendar {
  width: 100%;
  .header {
    width: 100%;
    height: 48px;
    padding: 0 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-sizing: border-box;
    background: #f6f7f9;
    &_left {
      font-size: 14px;
      font-family: PingFangSC-Semibold, PingFang SC;
      font-weight: 600;
      color: #2b2c2d;
      display: flex;
      align-items: center;
      .prev_btn {
        margin-right: 4px;
        display: flex;
        align-items: center;
        font-size: 24px;
        font-weight: 6000;
      }
      .next_btn {
        margin-left: 4px;
        align-items: center;
        display: flex;
        font-size: 24px;
        font-weight: 6000;
        .r180 {
          transform: rotate(180deg);
        }
      }
    }
    &_right {
      display: flex;
      align-items: center;
      font-size: 14px;
      color: #b4bccc;
      &_btn {
        display: flex;
        align-items: center;
        margin-left: 24px;
      }
      span {
        display: inline-block;
        margin-left: 2px;
        font-size: 12px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
      }
      .active {
        color: #046eff;
        span {
          padding: 2px;
          background: rgba(4, 110, 255, 0.1);
          border-radius: 4px;
          color: #046eff;
        }
      }
    }
  }
  .main {
    width: 100%;
    background: #f6f7f9;
    box-shadow: inset 0px -1px 0px 0px #d8dde7;
    padding-bottom: 16px;
    .title {
      width: 100%;
      min-height: 18px;
      box-shadow: inset 0px -1px 0px 0px #d8dde7;
      display: flex;
      align-items: center;
      justify-content: center;
      box-sizing: border-box;
      &_item {
        flex: 1 1 calc(99% / 7);
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        .text {
          width: 30px;
          text-align: center;
          height: 18px;
          font-size: 10px;
          font-family: PingFangSC-Regular, PingFang SC;
          font-weight: 400;
          color: #2b2c2d;
        }
      }
    }
    .list {
      width: 100%;
      box-sizing: border-box;
      display: flex;
      justify-content: center;
      flex-wrap: wrap;
      padding-top: 8px;
      &_item {
        flex: 1 1 calc(99% / 7);
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        padding-top: 8px;
        padding-bottom: 8px;
        .num {
          width: 30px;
          height: 24px;
          line-height: 24px;
          text-align: center;
          font-size: 17px;
          font-family: PingFangSC-Medium, PingFang SC;
          font-weight: 500;
          color: #2b2c2d;
          position: relative;
          // margin-top: 0.4267rem;
        }
        .active {
          background: #046eff;
          border-radius: 12px;
          color: #fff;
        }
        .num_rest::after {
          content: "休";
          display: inline-block;
          width: 8px;
          height: 8px;
          font-size: 8px;
          font-family: PingFangSC-Medium, PingFang SC;
          font-weight: 500;
          color: #727f93;
          position: absolute;
          right: -8px;
          top: -8px;
        }
        .num_abnormal::after {
          content: "异";
          display: inline-block;
          width: 8px;
          height: 8px;
          font-size: 8px;
          font-family: PingFangSC-Medium, PingFang SC;
          font-weight: 500;
          color: rgba(247, 106, 80, 0.8);
          position: absolute;
          right: -8px;
          top: -8px;
        }
        .num_noy_month {
          color: #b4bccc;
        }
        .dot {
          width: 4px;
          height: 4px;
          background: #046eff;
          position: absolute;
          bottom: 0;
          left: 50%;
          transform: translate(-50%, 0);
          border-radius: 50%;
        }
        .red {
          background-color: red;
        }
        .gray {
          background-color: gray;
        }
      }
    }
    .list_height6 {
      height: 248px;
      overflow-y: hidden;
    }
    .list_height5 {
      height: 207px;
      overflow-y: hidden;
    }
  }
}
</style>